package com.mcp;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpSyncServer;
import io.modelcontextprotocol.server.transport.StdioServerTransportProvider;
import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpServerTransportProvider;
import org.springframework.ai.mcp.McpToolUtils;
import org.springframework.ai.support.ToolCallbacks;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;

@Configuration
public class McpServerConfig {

    /**
     * stdio 方式
     * @return
     */
    @Bean
    @ConditionalOnProperty(prefix = "transport", name = "mode", havingValue = "stdio")
    public StdioServerTransportProvider stdioServerTransportProvider() {
        return new StdioServerTransportProvider();
    }

    /**
     * sse 方式
     * @return
     */
    @Bean
    @ConditionalOnProperty(prefix = "transport", name = "mode", havingValue = "sse")
    public WebFluxSseServerTransportProvider sseServerTransportProvider() {
        return new WebFluxSseServerTransportProvider(new ObjectMapper(), "/mcp/message");
    }

    /**
     * Spring WebFlux 用于启动 HTTP 的服务器发送事件（SSE）传输的路由器功能
     * @param transportProvider
     * @return
     */
    @Bean
    @ConditionalOnProperty(prefix = "transport", name = "mode", havingValue = "sse")
    public RouterFunction<?> mcpRouterFunction(WebFluxSseServerTransportProvider transportProvider) {
        return transportProvider.getRouterFunction();
    }

    /**
     *  client
     * 作为 ToolCallback 类 注入 到 mcp server 的服务
     * @return
     */
    @Bean
    public McpToolClient mcpToolClient() {
        return new McpToolClient();
    }


    /**
     *
     * @param transportProvider 传输层实现（如 STDIO 或 SSE），由前面配置的条件化 Bean 提供。
     * @param mcpToolClient 上一步注册的工具客户端 Bean。
     * @return
     */
    @Bean
    public McpSyncServer mcpServer(McpServerTransportProvider transportProvider, McpToolClient mcpToolClient) { // @formatter:off

        // 使用资源支持配置服务器功能
        var capabilities = McpSchema.ServerCapabilities.builder()
                .tools(true) // 启用工具支持，允许客户端发现、调用服务端工具
                .logging() // 启用日志记录功能，便于调试和监控
                .build();

        // 创建具备工具和资源双重功能的服务器
        // McpServer.sync(transportProvider) 使用指定的传输方式创建同步服务器
        McpSyncServer server = McpServer.sync(transportProvider)
                // 设置服务器名称和版本号，用于握手阶段标识
                .serverInfo("MCP Demo Weather Server", "1.0.0")
                // 设置服务器支持的功能（如工具、资源、日志等）
                .capabilities(capabilities)
                // 添加工具列表
                .tools(McpToolUtils.toSyncToolSpecifications(ToolCallbacks.from(mcpToolClient))) // Add @Tools
                // 开始构建
                .build();

        return server; // @formatter:on
    } // @formatter:on


}
